home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d13
/
ptv2n1.arc
/
L5.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-03-26
|
3KB
|
88 lines
; Finds and returns the greatest common divisor of two integers.
; Uses Euclid's Algorithm: divides the larger integer by the
; smaller; if the remainder is 0, the smaller integer is the gcd,
; otherwise the smaller integer becomes the larger integer, the
; remainder becomes the smaller integer, and the process is
; repeated. Avoids code recursion.
;
; Tested with MASM 5.1.
;
; C near-callable as:
; unsigned int gcd(unsigned int int1, unsigned int int2);
; Parameter structure:
parms struc
dw ? ;pushed BP
dw ? ;pushed return address
int1 dw ? ;integers for which to find
int2 dw ? ; the gcd
parms ends
.model small
.code
public _gcd
align 2
_gcd proc near
push bp ;preserve caller's stack frame
mov bp,sp ;set up our stack frame
push si ;preserve caller's register variables
push di
;Swap if necessary to make sure that int1 >= int2
mov ax,int1[bp]
mov bx,int2[bp]
cmp ax,bx ;is int1 >= int2?
jnb IntsSet ;yes, so we're all set
xchg ax,bx ;no, so swap int1 and int2
IntsSet:
; Now loop, dividing int1 by int2 and checking the remainder, until
; the remainder is 0. At each step, if the remainder isn't 0, assign
; int2 to int1, and the remainder to int2, then repeat.
GCDLoop:
;if the remainder of int1 divided by
; int2 is 0, then int2 is the gcd
sub dx,dx ;prepare int1 in DX:AX for division
div bx ;int1/int2; remainder is in DX
and dx,dx ;is the remainder zero?
jz Done ;yes, so int2 (BX) is the gcd
;no, so move int2 to int1 and the
; remainder to int2, and repeat the
; process
mov ax,bx ;int1 = int2;
mov bx,dx ;int2 = remainder from DIV
;---start of loop unrolling; the above is repeated three times---
sub dx,dx ;prepare int1 in DX:AX for division
div bx ;int1/int2; remainder is in DX
and dx,dx ;is the remainder zero?
jz Done ;yes, so int2 (BX) is the gcd
mov ax,bx ;int1 = int2;
mov bx,dx ;int2 = remainder from DIV
;---
sub dx,dx ;prepare int1 in DX:AX for division
div bx ;int1/int2; remainder is in DX
and dx,dx ;is the remainder zero?
jz Done ;yes, so int2 (BX) is the gcd
mov ax,bx ;int1 = int2;
mov bx,dx ;int2 = remainder from DIV
;---
sub dx,dx ;prepare int1 in DX:AX for division
div bx ;int1/int2; remainder is in DX
and dx,dx ;is the remainder zero?
jz Done ;yes, so int2 (BX) is the gcd
mov ax,bx ;int1 = int2;
mov bx,dx ;int2 = remainder from DIV
;---end of loop unrolling---
jmp GCDLoop
align 2
Done:
mov ax,bx ;return the gcd
pop di ;restore caller's register variables
pop si
pop bp ;restore caller's stack frame
ret
_gcd endp
end